/*
 * CFrameBufferObject.cpp
 *
 *      Author: grifos
 */

#include <GL/glew.h>
#include "CFrameBufferObject.h"
#include <iostream>


/**
 * Constructeur
 */
CFrameBufferObject::CFrameBufferObject() {
	_TextureID = 0;
	_width = 0;
	_height = 0;
	_FBHandle = 0;
	_DBHandle = 0;
	_TextureType = GL_TEXTURE_2D;
	_Attachment = 0;
	_created = false;

}

CFrameBufferObject::~CFrameBufferObject() {
	// On supprime la texture et le framebuffer
	glDeleteTextures(1, &_TextureID);
	glDeleteFramebuffersEXT(1, &_FBHandle);
}

/**
 * Méthode qui dit qu'on commence à utiliser le fbo
 */
void CFrameBufferObject::BeginUse()
{
	glPushAttrib(GL_VIEWPORT_BIT);
	glViewport(0, 0, _width, _height);

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _FBHandle);

//	glPushAttrib(GL_COLOR_BUFFER_BIT | GL_PIXEL_MODE_BIT); // for GL_DRAW_BUFFER and GL_READ_BUFFER
//	glDrawBuffer(GL_BACK);
//	glReadBuffer(GL_BACK);
}


/**
 * Méthode qui dit qu'on arrete d'utiliser le fbo
 */
void CFrameBufferObject::EndUse()
{
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

	//glPopAttrib(); // GL_COLOR_BUFFER_BIT | GL_PIXEL_MODE_BIT
	glPopAttrib(); // GL_VIEWPORT_BIT
}

/**
 * Méthode de création du FBO
 */
int CFrameBufferObject::CreateFBO( GLuint w, GLuint h)
{
	_width = w;
	_height = h;

	// On crée la texture où sera stocké le contenu du render buffer
	glGenTextures( 1, &_TextureID );
	glBindTexture(_TextureType, _TextureID);
	glTexParameterf(_TextureType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(_TextureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(_TextureType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(_TextureType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	GLenum eTarget;
	GLuint nFrames;
	eTarget = GL_TEXTURE_2D;
	nFrames = 1;

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _width, _height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);

	// On crée un render buffer
	glGenFramebuffersEXT(1, &_FBHandle);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _FBHandle);

	// On attache le render buffer à la texture
	_Attachment = GL_COLOR_ATTACHMENT0_EXT;
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, eTarget, _TextureID, 0);

	//  On crée un depth buffer
	glGenRenderbuffersEXT(1, &_DBHandle);
	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, _DBHandle);
	glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, _width, _height);

	// attache le render buffer avec le depth buffer
	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, _DBHandle);

	// On check l'état du fbo pour savoir si il a bien été fait
	GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
	if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
	    return 0; // On retourne 0 si il y a eu un probleme

	// On retourne au frame buffer normal
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

	_created = true;
	return 1;
}

void CFrameBufferObject::BindTexture(GLuint textid)
{
	glActiveTextureARB(GL_TEXTURE0_ARB + textid);
	glEnable(_TextureType);
	glBindTexture(_TextureType, _TextureID);
}



void CFrameBufferObject::UnbindTexture(GLuint textid)
{
	glActiveTextureARB(GL_TEXTURE0_ARB + textid);
	glBindTexture( _TextureType, 0 );
	glDisable(_TextureType);
}



